<?php

namespace Anchu\Restful\Models;


use Illuminate\Database\Eloquent\Model as BaseModel;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

abstract class Model extends BaseModel
{

    /**
     * @function    表结构的定义，用于migrate生产表，request定义校验规则，以及表单空值的默认值查询处理
     * @return      TableSchema
     * @example
     * 使用方法1（推荐，有类型提示）：
     *  use Anchu\Restful\Models\Columns\ColumnFactory;
     *  $column = new ColumnFactory();
     *  return new TableSchema(
     *      tableName: 'table_name',
     *      comment: '测试用',
     *      columns: [
     *          'job' => $column->string(label: '工作', type: 'string'),
     *          'duration' => $column->varchar(label: '用工时段', comment: '给临时工用', rule: 'string|max:100'),
     *          'salary' => $column->char(label: '薪水', comment: '用逗号隔开', rule: 'string'),
     *          'num' => $column->integer(label: '招聘人数', unsigned: false),
     *          'status' => $column->tinyInteger(label: '状态', comment: '1:保存；2:发布（上架）；3：已下架；4:违规下架.'),
    v          ''experience' => $column->smallInteger(label: '工作经验', comment: '1：经验不限；2：1-3年；3：3-5年；4：5-：10年以上', default: 1),
     *          'payment' => $column->mediumInteger(label: '结薪方式', comment: '1：按月；2：按日', default: 1),
     *          'user_id' => $column->bigInteger(label: '用户id'),
     *          'yasi' => $column->numeric(label: '雅思成绩', rule: 'numeric|min:0|max:10'),
     *          'yasi_float' => $column->float(label: '雅思成绩1', rule: 'numeric|min:0|max:10'),
     *          'yasi_double' => $column->double(label: '雅思成绩2', rule: 'numeric|min:0|max:10'),
     *          'yasi_decimal' => $column->decimal(label: '雅思成绩3', rule: 'numeric|min:0|max:10'),
     *          'article' => $column->text(label: '雅思成绩3'),
     *          'article_tiny' => $column->text(label: '雅思成绩3', type: 'tinyText'),
     *          'article_medium' => $column->text(label: '雅思成绩3', type: 'mediumText'),
     *          'article_long' => $column->text(label: '雅思成绩3', type: 'longText'),
     *      ],
     *      keys: [
     *          'index_normal' => new Key(
     *              column: ['user_id']
     *          ),
     *          'index_unique' => new Key(
     *              column: ['created_at'],
     *              unique: true
     *          ),
     *          'index_union' => new Key(
     *              column: ['created_at', 'updated_at'],
     *              unique: true
     *          )
     *      ]
     *  );
     *
     *  使用方法2：
     *  return new TableSchema(
     *      tableName: 'table_name',
     *      comment: '测试用',
     *      columns: [
     *          'job' => new CString(label: '工作', type: 'string'),
     *          'duration' => new CVarchar(label: '用工时段', comment: '给临时工用', rule: 'string|max:100'),
     *          'salary' => new CChar(label: '薪水', comment: '用逗号隔开', rule: 'string'),
     *          'num' => new CInteger(label: '招聘人数', unsigned: false),
     *          'status' => new CTinyInteger(label: '状态', comment: '1:保存；2:发布（上架）；3：已下架；4:违规下架.'),
    v          'experience' => new CSmallInteger(label: '工作经验', comment: '1：经验不限；2：1-3年；3：3-5年；4：5-10年；5：10年以上', default: 1),
     *          'payment' => new CMediumInteger(label: '结薪方式', comment: '1：按月；2：按日', default: 1),
     *          'user_id' => new CBigInteger(label: '用户id'),
     *          'yasi' => new CNumeric(label: '雅思成绩', rule: 'numeric|min:0|max:10'),
     *          'yasi_float' => new CFloat(label: '雅思成绩1', rule: 'numeric|min:0|max:10'),
     *          'yasi_double' => new CDouble(label: '雅思成绩2', rule: 'numeric|min:0|max:10'),
     *          'yasi_decimal' => new CDecimal(label: '雅思成绩3', rule: 'numeric|min:0|max:10'),
     *          'article' => new CText(label: '雅思成绩3'),
     *          'article_tiny' => new CText(label: '雅思成绩3', type: 'tinyText'),
     *          'article_medium' => new CText(label: '雅思成绩3', type: 'mediumText'),
     *          'article_long' => new CText(label: '雅思成绩3', type: 'longText'),
     *      ],
     *      keys: [
     *          'index_normal' => new Key(
     *              column: ['user_id']
     *          ),
     *          'index_unique' => new Key(
     *              column: ['created_at'],
     *              unique: true
     *          ),
     *          'index_union' => new Key(
     *              column: ['created_at', 'updated_at'],
     *              unique: true
     *          )
     *      ]
     *  );
    */
    public static abstract function table(): TableSchema;

    /**
     * 用于字段的格式校验校验规则设置
     */
    public static function rules()
    {
        $rules = [];
        $columns = static::table()->columns ?? [];
        foreach ($columns as $column => $obj) {
            $rules[$column] = $obj->rule();
        }
        return $rules;
    }

    /**
     * 获取字段的属性信息
     */
    public static function attributes()
    {
        $attributes = [];
        $columns = static::table()->columns ?? [];
        foreach ($columns as $column => $obj) {
            $attributes[$column] = $obj->attribute();
        }
        return $attributes;
    }

    public static function defaults() {
        $defaults = [];
        $columns = static::table()->columns ?? [];
        foreach ($columns as $column => $obj) {
            $defaults[$column] = $obj->default;
        }
        return $defaults;
    }

    /**
     * 创建表，用于migrate
     */
    public static function createTable()
    {
        $model = static::table();
        Schema::dropIfExists($model->tableName);
        // 先创建基本结构
        Schema::create($model->tableName, function (Blueprint $table) use ($model) {
            $table->id();
            $table->comment($model->comment);
            $table->engine = $model->engine;
            $table->charset = $model->charset;
        });
        // 具体字段在字段类中去实现
        foreach ($model->columns as $name => $column) {
            $column->createColumn($model->tableName, $name);
        }
        // 创建辅助结构
        Schema::table($model->tableName, function (Blueprint $table) use ($model) {
            $table->timestamps(); // updated_at & created_at
            if ($model->softDelete) $table->softDeletes();
        });

        // 具体索引在索引类中创建
        foreach ($model->keys as $name => $key) {
            $key->createKey($model->tableName, $name);
        }
    }

    /**
     * 删除表
     */
    public static function dropTable()
    {
        $model = static::table();
        Schema::dropIfExists($model->tableName);
    }

    /**
     * 为数组 / JSON 序列化准备日期。
     *
     * @param \DateTimeInterface $date
     * @return string
     */
    protected function serializeDate(\DateTimeInterface $date)
    {
        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
    }
}
